﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace RTF2XML
{
    class TableControl : Control
    {
        #region Private Variables
        /// <summary>
        /// Parsed control text maching the list
        /// </summary>
        private string sControl = "";

        /// <summary>
        /// Input control text
        /// </summary>
        private string sControlText = "";

        /// <summary>
        /// Number following a numbered control
        /// </summary>
        private int iNumberedControlNum = -1;
        #endregion

        #region Lists of Controls
        public static new List<string> lstControls = new List<string>()
        {
             "trowd", "row", "lastrow", "tcelld", "nestcell", "nestrow", "nesttableprops", "nonesttables", "cell",
             "clmgf", "clmrg", "clvmgf", "clvmrg", "tbllkborder", "tbllkshading", "tbllkfont", "tbllkcolor",
             "tbllkbestfit", "tbllkhdrrows", "tbllklastrow", "tbllkhdrcols", "tbllklastcol", "tbllknorowband",
             "tbllknocolband", "taprtl", "trhdr", "trkeep", "trkeepfollow", "trqc", "trql", "trqr", "trbgbdiag",
             "trbgcross", "trbgdcross", "trbgdkbdiag", "trbgdkcross", "trbgdkdcross", "trbgdkfdiag", "trbgdkhor",
             "trbgdkvert", "trbgfdiag", "trbghoriz", "trbgvert", "clFitText", "clNoWrap", "clhidemark", "clins",
             "cldel", "clmrgd", "clmrgdr", "clsplit", "clsplitr", "tabsnoovrlp", "tphcol", "tphmrg", "tphpg", "tposxc",
             "tposxi", "tposxl", "tposxo", "tposxr", "tposyb", "tposyc", "tposyil", "tposyin", "tposyout", "tposyt",
             "tpvmrg", "tpvpara", "tpvpg", "rtlrow", "ltrrow", "trbrdrt", "trbrdrl", "trbrdrb", "trbrdrr", "trbrdrh",
             "trbrdrv", "brdrnil", "clbrdrb", "clbrdrt", "clbrdrl", "clbrdrr", "cldglu", "cldgll", "clshdrawnil",
             "clbghoriz", "rawclbghoriz", "clbgvert", "rawclbgvert", "clbgfdiag", "rawclbgfdiag", "clbgbdiag",
             "rawclbgbdiag", "clbgcross", "rawclbgcross", "clbgdcross", "rawclbgdcross", "clbgdkhor", "rawclbgdkhor",
             "clbgdkvert", "rawclbgdkvert", "clbgdkfdiag", "rawclbgdkfdiag", "clbgdkbdiag", "rawclbgdkbdiag",
             "clbgdkcross", "rawclbgdkcross", "clbgdkdcross", "rawclbgdkdcross", "clvertalt", "clvertalc", "clvertalb",
             "cltxlrtb", "cltxtbrl", "cltxbtlr", "cltxlrtbv", "cltxtbrlv"
        };

        public static new List<string> lstNumberedControls = new List<string>()
        {
             "irow", "irowband", "trgaph", "cellx", "trauth", "trdate", "trautofit", "trleft", "trrh", "trpaddb",
             "trpaddl", "trpaddr", "trpaddt", "trpaddfb", "trpaddfl", "trpaddfr", "trpaddft", "trspdb", "trspdl",
             "trspdr", "trspdt", "trspdfb", "trspdfl", "trspdfr", "trspdft", "trpadob", "trpadol", "trpador",
             "trpadotN", "trpadofb", "trpadofl", "trpadofr", "trpadoft", "trspob", "trspol", "trspor", "trspot",
             "trspofb", "trspofl", "trspofr", "trspoft", "trwWidth", "trftsWidth", "trwWidthB", "trftsWidthB",
             "trwWidthA", "trftsWidthA", "tblind", "tblindtype", "trcbpat", "trcfpat", "trpat", "trshdng", "clpadl",
             "clpadt", "clpadb", "clpadr", "clpadfl", "clpadft", "clpadfb", "clpadfr", "clspl", "clspt", "clspb",
             "clspr", "clspfl", "clspft", "clspfb", "clspfr", "clwWidth", "clftsWidth", "clinsauth", "clinsdttm",
             "cldelauth", "cldeldttm", "clmrgdauth", "clmrgddttm", "tdfrmtxtLeft", "tdfrmtxtRight", "tdfrmtxtTop",
             "tdfrmtxtBottom", "tposnegx", "tposnegy", "tposx", "tposy", "clshdng", "clshdngraw", "clcfpat",
             "clcfpatraw", "clcbpat", "clcbpatraw"
        };

        public static new List<string> lstDestinationControls = new List<string>()
        {
            "tc", "tcn"
        };
        #endregion

        /// <summary>
        /// Creates a new table control with the given control text
        /// </summary>
        /// <param name="controlText"></param>
        public TableControl(string controlText)
        {
            //Uncomment below line if you want to keep the input text (for debugging)
            //this.sControlText = controlText;

            //If the control is a regular control
            if (lstControls.Contains(controlText))
            {
                this.sControl = controlText;
            }
            //If the control is a destination control
            else if (lstDestinationControls.Contains(controlText))
            {
                this.sControl = controlText;
                base.bDestination = true;
            }
            //Check to see if control is a numbered control
            else
            {
                foreach (string control in lstNumberedControls)
                {
                    //If the input text starts with the control
                    if (controlText.StartsWith(control))
                    {
                        //Try to parse out the number from the input
                        string number = controlText.Replace(control, "");
                        int n = -1;
                        if (int.TryParse(number, out n))
                        {
                            //If you were able to parse out the number then it's a valid control
                            this.sControl = control;
                            this.iNumberedControlNum = n;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Checks to see if the input control is part of the control class
        /// </summary>
        /// <param name="sControl">control to check</param>
        /// <returns>true if control is in table control class, false otherwise</returns>
        public static bool IsPartOfControl(string sControl)
        {
            //If it's a regular control or a destination control
            if (lstControls.Contains(sControl) || lstDestinationControls.Contains(sControl))
            {
                return true;
            }

            //Check to see if it's a numbered control
            foreach (string control in lstNumberedControls)
            {
                if (sControl.StartsWith(control))
                {
                    //Check to see if the number can be parsed out of the control
                    string number = sControl.Replace(control, "");
                    int n = 0;
                    if (int.TryParse(number, out n))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// Adds the control to the xml parent node in sequence with the other nodes
        /// </summary>
        /// <param name="xmlParentNode"></param>
        public override void AddXML(ref XmlElement xmlParentNode)
        {
            int iSeqNum = 0;

            if (xmlParentNode.HasChildNodes)
            {
                //Get the last sequence number of the other children nodes
                string seqNum = xmlParentNode.LastChild.Attributes["seq"].Value;
                if (int.TryParse(seqNum, out iSeqNum))
                {
                    //Increment the sequence number
                    iSeqNum++;
                }
                else
                {
                    throw new Exception("Sequence number is not valid");
                }
            }

            //Add a new element for the control
            XmlElement child = xmlParentNode.OwnerDocument.CreateElement(this.sControl);
            //Add the sequence number
            child.SetAttribute("seq", iSeqNum.ToString());
            //If the control is a numbered control
            if (this.iNumberedControlNum != -1)
            {
                //Add the number as an attribute
                child.SetAttribute("number", this.iNumberedControlNum.ToString());
            }
            //Add element to the parent node
            xmlParentNode.AppendChild(child);
        }
    }
}
